package ncit.bluetooth.control;

import ncit.bluetooth.connect.BluetoothChatService;
import ncit.bluetooth.connect.BluetoothDeviceSearch;
import ncit.bluetooth.robots.Commands;
import ncit.bluetooth.settings.BluetoothControlSettings;
import ncit.bluetooth.settings.BluetoothControlSettingsActivity;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class BluetoothControlActivity extends Activity {

	/**
	 * Used for Debugging.
	 */
	public static final boolean DEBUG = true;
	private static final String TAG = "bluetooth.control.BluetoothControlActivity";
	
	/**
	 * Constants used for this class's Handler.
	 */
	public static final int MESSAGE_SEND = 0;
	public static final int MESSAGE_RECEIVE = 1;
	public static final int MESSAGE_WITH_WORKINGTHREAD_HANDLER = 2;
	public static final int MESSAGE_TOAST = 3;
	public static final String TOAST = "TOAST";

	
	/**
	 * Constants used by the onActivityResult method
	 */
	private static final int REQUEST_ENABLE_BT = 2;
	private static final int REQUEST_CONNECT_DEVICE = 0;
	private static final int REQUEST_CHANGE_SETTINGS = 1;

	public static PowerManager powerManager;// TODO: make the wake lock work.

	/**
	 * Used to show the used to what device he's connecting to.
	 */
	private TextView name;
	private TextView macAddr;
	private TextView distance_to_object;// TODO:

	private WorkingThread workingThread;
	private AccListener _accListener = null;
	private BluetoothAdapter mBluetoothAdapter = null;
	private BluetoothChatService mChatService = null;
	private boolean stop = false;

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);

		// The texts that show which device we connected to
		name = (TextView) findViewById(R.id.nume);
		macAddr = (TextView) findViewById(R.id.mac);
		distance_to_object = (TextView) findViewById(R.id.distance_to_object);

		name.setText("Device name: ");
		macAddr.setText("Device address: ");

		// instantiate the working thread
		workingThread = new WorkingThread(mHandler);

		//instantiate the accelerometer listener
		_accListener = new AccListener(workingThread);
		
		// get the sensor manager and enlist this class as a listener
		SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);

		sensorManager.registerListener(_accListener,
				sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
				SensorManager.SENSOR_DELAY_NORMAL);

		setConnectButton();

		setStartConnectionButton();

		setStopConnectionButton();

		setBrakeButton();

		setParkingButton();
		
		//load settings
		SharedPreferences settings = getSharedPreferences(BluetoothControlSettingsActivity.PREFS_NAME, 0);
		new BluetoothControlSettings(settings).loadSettings();
				
		if(DEBUG) Log.d(TAG,"Application started.");
	}

	/**
	 * Method that binds the Connect button on the screen with an
	 * OnClickListener that launches the BluetoothDeviceSearch activity.
	 * 
	 */
	public void setConnectButton() {

		Button connectButton = (Button) findViewById(R.id.connect);// connection
		// button
		connectButton.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {

				mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

				if (!mBluetoothAdapter.isEnabled()) {

					Intent enableIntent = new Intent(
							BluetoothAdapter.ACTION_REQUEST_ENABLE);
					startActivityForResult(enableIntent, REQUEST_ENABLE_BT);

				}

				while (!mBluetoothAdapter.isEnabled()) {}
				
				
				// Launch the DeviceListActivity to see devices and do scan
				Intent i = new Intent(getApplicationContext(),
						BluetoothDeviceSearch.class);

				// instantiate and get the instance of the singleton class
				// BluetoothChatService, used for communicating with the bluetooth device
				BluetoothChatService.instantiate(getApplicationContext(),
						mHandler);
				mChatService = BluetoothChatService.getInstance();
				mChatService.start();
				_accListener.setChatService(mChatService);

				startActivityForResult(i, REQUEST_CONNECT_DEVICE);
				
				if(DEBUG) Log.d(TAG,"User pressed the Connect button.");
			}

		});
	}

	/**
	 * Method that binds the Start Connection Button on the screen with an
	 * OnclickListener that reatins x,y,z values of the acc, used to scale and
	 * tweak the accelerometer. This is done in the method start() of the
	 * AccListener class. After finding a device from the BluetoothDeviceSearch,
	 * pressing this button will establlish the link.
	 */
	public void setStartConnectionButton() {
		Button startConnectButton = (Button) findViewById(R.id.button1);
		startConnectButton.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {

				if ((mChatService == null)
						|| (mChatService.getState() != BluetoothChatService.STATE_CONNECTED)) {

					Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
					Bundle bundle = new Bundle();
					bundle.putString(TOAST,
							"Please Connect to the device first.");
					if(DEBUG) Log.d(TAG, "Device not found. Has to search for one first.");
					msg.setData(bundle);
					msg.sendToTarget();
					return;
				}

				if (!workingThread.isAlive()){
					workingThread.startWorking();
					workingThread.start();
					}

				_accListener.start();

				Message msg = workingThread.getHandler().obtainMessage(
						WorkingThread.MESSAGE_START);
				msg.sendToTarget();
				
				if(DEBUG) Log.d(TAG, "Succesfully established a link between devices. ");
			}
		});
	}

	/**
	 * Method that binds the Stop Connection button on the screen with an
	 * OnClickListener that terminates the current Bluetooth Connection and
	 * stops all the running threads.
	 */
	public void setStopConnectionButton() {
		
		Button stopConnectButton = (Button) findViewById(R.id.button2);
		
		stopConnectButton.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {

				// we send a stop message
				Message msg = workingThread.getHandler().obtainMessage(
						WorkingThread.MESSAGE_STOP);
				msg.sendToTarget();

				workingThread.stopWorking();
				mChatService.stop();
			}

		});

		if(DEBUG) Log.d(TAG,"User pressed the Stop Connection button.");
	}

	/**
	 * Method that binds the Break button on the screen with an OnClickListener
	 * that will tell the WorkingThread to not send anymore commands to the
	 * device.
	 */
	public void setBrakeButton() {
		
		Button brakeButton = (Button) findViewById(R.id.frana);
		
		brakeButton.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {

				// breaking puts the motors and the direction at 0 power.
				if (!stop) {

					_accListener.stop();
					stop = true;
					arg0.setBackgroundResource(R.drawable.but2);

					// sends a break message
					Message msg = workingThread.getHandler().obtainMessage(
							WorkingThread.MESSAGE_BREAK);
					msg.sendToTarget();

					msg = mHandler.obtainMessage(MESSAGE_TOAST);
					Bundle bundle = new Bundle();
					bundle.putString(TOAST, "Braking ...");
					msg.setData(bundle);
					msg.sendToTarget();

					// Toast.makeText(BluetoothControlActivity.this,
					// " Braking ... ", Toast.LENGTH_SHORT).show();

				} else {

					_accListener.start();
					stop = false;
					arg0.setBackgroundResource(R.drawable.but1);
					// Toast.makeText(BluetoothControlActivity.this,
					// " Starting ... ", Toast.LENGTH_SHORT).show();

					Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
					Bundle bundle = new Bundle();
					bundle.putString(TOAST, "Braking ...");
					msg.setData(bundle);
					msg.sendToTarget();

				}
				if(DEBUG) Log.d(TAG,"User pressed the Brake button.");
			}
			
		});
	}

	/**
	 * Method that binds the Park button on the screen with an OnClickListener
	 * that sends a message to the WorkingThread, telling it to start a
	 * predetermined parallel parking type of moves.
	 */
	public void setParkingButton() {
		
		Button parkingButton = (Button) findViewById(R.id.parcare);
		parkingButton.setOnClickListener(new OnClickListener() {

			public void onClick(View arg0) {

				Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
				Bundle bundle = new Bundle();
				bundle.putString(TOAST, "Parking ...");
				msg.setData(bundle);
				msg.sendToTarget();

				msg = workingThread.getHandler().obtainMessage(
						WorkingThread.MESSAGE_PARK);
				msg.sendToTarget();

				// we automatically stop it
				stop = true;

				msg = workingThread.getHandler().obtainMessage(
						WorkingThread.MESSAGE_BREAK);
				msg.sendToTarget();

				if(DEBUG) Log.d(TAG,"User pressed the Park button.");
			}
		});

	}

	@Override
	public void onPause() {
		super.onPause();

		if (workingThread != null)
			if (workingThread.isAlive() && !workingThread.isInterrupted())
				workingThread.interrupt();

		if(DEBUG) Log.d(TAG,"Application is paused.");
	}

	@Override
	public void onDestroy() {

		super.onDestroy();

		if (workingThread != null)
			if (workingThread.isAlive() && !workingThread.isInterrupted())
				workingThread.interrupt();

		if (mChatService != null) {
			mChatService.stop();
		}

		SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
		sensorManager.unregisterListener(_accListener);
		
		if(DEBUG) Log.d(TAG,"Application is destroyed.");
	}

	@Override
	public void onResume() {

		super.onResume();

		if (workingThread != null)
			if (!workingThread.isAlive() && workingThread.isInterrupted())
				workingThread.start();
		if(DEBUG) Log.d(TAG, "Application is resumed.");
	}

	/**
	 * Method to inflate the menu item when pressing the menu button.
	 */
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu_pg, menu);
		return true;

	}

	/**
	 * Method which describes what happenes when a menu item is selected.
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		switch (item.getItemId()) {

		case R.id.settings:

			//start the bluetooth control settings activity
			Intent i = new Intent(this, BluetoothControlSettingsActivity.class);
			startActivityForResult(i, REQUEST_CHANGE_SETTINGS);

			if(DEBUG) Log.d(TAG,"User pressed the Settings button.");
			return true;

		case R.id.exit:
			
			if(DEBUG) Log.d(TAG,"User pressed the Exit button.");
			finish();
			
			return true;

		}
		return false;
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		
		if(DEBUG) Log.d(TAG,"Activity Bluetooth Device Search has ended.");

		switch (requestCode) {
		
		case REQUEST_CONNECT_DEVICE:
			
			// When DeviceListActivity returns with a device to connect
			if (resultCode == Activity.RESULT_OK) {
				// Get the device MAC address
				String address = data.getExtras().getString(
						BluetoothDeviceSearch.EXTRA_DEVICE_ADDRESS);
				// Get the BLuetoothDevice object
				BluetoothDevice device = mBluetoothAdapter
						.getRemoteDevice(address);
				// Attempt to connect to the device
				name.setText("Device name: " + device.getName());
				macAddr.setText("Device address: " + device.getAddress());

				mChatService.connect(device);

			}
			break;
			
		case REQUEST_ENABLE_BT:
			
			// When the request to enable Bluetooth returns
			if (resultCode == Activity.RESULT_OK) {

				
				
			} else {
				
				if(DEBUG) Log.d(TAG,"User did not enable bluetooth or an error has occured.");
				finish();
				
			}
			
			break;
			
		case REQUEST_CHANGE_SETTINGS:
			
			Log.d(TAG, "User changed the settings.");
			Message msg = workingThread.getHandler().obtainMessage(WorkingThread.MESSAGE_ROBOT_CHANGE, BluetoothControlSettings.DEVICE_TYPE, 0);
			msg.sendToTarget();
			
			break;
			
		}
	}

	// The Handler that gets information back from the BluetoothChatService
	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {

			Message msg1;
			switch (msg.what) {
			case MESSAGE_SEND:

				mChatService.write((byte[]) msg.obj);
				break;

			case MESSAGE_RECEIVE:

				msg1 = workingThread.getHandler().obtainMessage(
						WorkingThread.MESSAGE_RECV, msg.obj);
				msg1.sendToTarget();
				Log.i("recv", "am primit " + msg1.obj + " " + msg.obj);

				break;

			case MESSAGE_WITH_WORKINGTHREAD_HANDLER:
				if (msg.arg1 == Commands.ULTRASOUND_SENSOR) {

					// TODO: Sensors.
					/*
					 * if(msg.arg2 < 25){
					 * distance_to_object.setText("Obstacole in " + msg.arg2 +
					 * " cm ");
					 * 
					 * if(msg.arg2 < 5 && !breaked){
					 * 
					 * msg1 =
					 * workingThread.getHandler().obtainMessage(WorkingThread
					 * .MESSAGE_BREAK); msg1.sendToTarget(); breaked = true; } }
					 * else distance_to_object.setText("Drum liber");
					 */

				} else if (msg.arg1 == Commands.LEFT_BACK_TOUCH_SENSOR
						&& msg.arg2 == 1) {

					distance_to_object.setText("Obstacole in back left.");

				} else if (msg.arg1 == Commands.RIGHT_BACK_TOUCH_SENSOR
						&& msg.arg2 == 1) {
					distance_to_object.setText("Obstacole in back right.");
				} else
					distance_to_object.setText("No obstacles.");

				break;

			case MESSAGE_TOAST: {

				String string = msg.getData().getString(TOAST);
				Toast.makeText(getBaseContext(), string, Toast.LENGTH_SHORT);

				break;
			}
			}
		}
	};
}